package org.example.uhy.repository.config;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.util.MultiValueMap;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;

public class EnableOrmAutoConfigRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
        MultiValueMap<String, Object> v = importingClassMetadata.getAllAnnotationAttributes(EnableOrmAutoConfig.class.getName());
        if (v != null) {
            BeanDefinition transactionManager = BeanDefinitionBuilder
                    .genericBeanDefinition(DataSourceTransactionManager.class)
                    .addPropertyReference("dataSource", (String) v.getFirst("dataSourceBeanName"))
                    .getBeanDefinition();
            registry.registerBeanDefinition("transactionManager", transactionManager);

            BeanDefinition sqlSessionFactory = BeanDefinitionBuilder
                    .genericBeanDefinition(SqlSessionFactoryBean.class)
                    .addPropertyReference("dataSource", (String) v.getFirst("dataSourceBeanName"))
                    .addPropertyValue("configuration", configuration())
                    .getBeanDefinition();
            registry.registerBeanDefinition("sqlSessionFactory", sqlSessionFactory);

            BeanDefinition sqlSessionTemplate = BeanDefinitionBuilder
                    .genericBeanDefinition(org.mybatis.spring.SqlSessionTemplate.class)
                    .addConstructorArgReference("sqlSessionFactory")
                    .getBeanDefinition();
            registry.registerBeanDefinition("sqlSessionTemplate", sqlSessionTemplate);

            BeanDefinition mapperScannerBeanDefinition = BeanDefinitionBuilder
                    .genericBeanDefinition(MapperScannerConfigurer.class)
                    .addPropertyValue("basePackage", v.getFirst("daoBasePackage"))
                    .addPropertyValue("sqlSessionFactoryBeanName", "sqlSessionFactory")
                    .getBeanDefinition();
            registry.registerBeanDefinition("mapperScannerConfigurer", mapperScannerBeanDefinition);
        }
    }

    private org.apache.ibatis.session.Configuration configuration() {
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.getTypeHandlerRegistry().register(LocalDateTime.class, new LocalDateTimeTypeHandler(ZoneId.systemDefault()));
        configuration.getTypeHandlerRegistry().register(LocalDate.class, new LocalDateTypeHandler(ZoneId.systemDefault()));
        return configuration;
    }
}
